<?php
namespace app\api\model;

use app\api\library\Exception\DataMissException;
use think\Exception;
use think\Model;

class Base extends Model {
    /**
     * 是否开启自动写入功能
     * @var bool
     */
    protected $autoWriteTimestamp = 'int';
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    /**
     * 构造函数
     * @date 2020-07-16
     * @param $data
     */
    public function __construct($data = []) {
        parent::__construct($data);
    }

    public function getImageAttr($value,$data){
        if (!$value) return '';
        return cdnurl($value);
    }

    public function getImagesAttr($value,$data)
    {
        if (!$value) return [];
        if (is_array($value)) return $value;
        $arr = explode(',', $value);
        $data = [];
        foreach ($arr as $k => $v) {
            $data[$k] = cdnurl($v);
        }
        return $data;
    }

    public function getAvatarAttr($value, $data){
        if (!$value) return '';
        return cdnurl($value);
    }

    public function getCreatetimeAttr($value){
        return date('Y-m-d',$value);
    }

    /**
     * 单条查询
     * @param array $where 查询条件
     * @param string $field 查询field
     * @param string $order 查询排序
     * @param boolean $isFail 是否直接返回错误
     * @return array|false|mixed|\PDOStatement|string|Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function findOrFail($where = [],$isFail = true ,$field = '*',$order = "") {

        if (empty($order)) {
            if ($this->getPk() != null) {
                $order = $this->getPk() . ' desc';
            } else {
                $order = 'id desc';
            }
        }
        $array = explode(',', $field);
        $sql = $this->connect_where($where);
        if($isFail){//如果直接返回错误
            $sql->failException(true);
        }
        try{
            if(isset($where['hasWhere'])){
                $field = $this->changeField($field);
                $order = $this->changeOrder($order);
            }
            if (count($array) <= 1) {
                return $sql->value($field);
            } else {
                if($isFail){
                    return  $sql->field($field)->order($order)->find()->toArray();
                }else{
                    $data  = $sql->field($field)->order($order)->find();

                    if($data){
                        $data = $data->toArray();
                    }
                    return $data;
                }
            }

        }catch (Exception $exception){
            throw new DataMissException($exception);
        }
    }

    /**
     * 获取列表信息（无分页）
     * @param array $where 查询条件
     * @param string $field 查询字段
     * @param string $order 排序方式\
     * @param string $limit 查询条数\
     * @param boolean $isFail 是否直接返回错误
     * @return array|false|\PDOStatement|string|\think\Collection
     */
    public function selectOrFail($where, $isFail = true,$field = '*', $order ='',$limit = '') {
        if (empty($order)) {
            if ($this->getPk() != null) {
                $order = $this->getPk() . ' desc';
            } else {
                $order = 'id desc';
            }
        }
        try{
            $sql = $this->connect_where($where);
            if($isFail){
                $sql->failException(true);
            }
            if(isset($where['hasWhere'])){
                $field = $this->changeField($field);
                $order = $this->changeOrder($order);
            }
            if ($limit) $sql->limit($limit);
            return collection($sql->orderRaw($order)->field($field)->select())->toArray();
        }catch (Exception $exception){
            throw new DataMissException($exception);
        }
    }

    /**
     * 获取列表信息 (分页)
     * @param $page
     * @param $where array 查询条件
     * @param string $field string 查询字段
     * @param string $order string 查询排序
     * @param string $per_page_number int 每页显示数量
     */
    public function pageSelect($page,$where,$field = '*',$order='',$per_page_number = 10){
        if (empty($order)) {
            if ($this->getPk() != null) {
                $order = $this->getPk() . ' desc';
            } else {
                $order = 'id desc';
            }
        }
        try{
            $sql = $this->connect_where($where);
            if(isset($where['hasWhere'])){
                $field = $this->changeField($field);
                $order = $this->changeOrder($order);
            }
            return $sql->field($field)->order($order)->paginate($per_page_number, false, [
                'page' => $page,
            ]);
        }catch (Exception $exception){
            throw new DataMissException($exception);
        }
    }

    /**
     * 修改/新增数据
     * @param $data
     * @return bool|mixed
     */
    public function dataUpdate($data) {
        if (empty($data)) {
            return false;
        } else {
            if (array_key_exists($this->getPk(), $data) && !empty($data[$this->getPk()])) { // 数据修改
                $result = $this->allowField(true)->edit($data);
            } else { // 数据插入
                $result = $this->allowField(true)->add($data);
            }
            return $result;
        }
    }

    /**
     * 新增数据
     * @param $data
     * @return bool|mixed
     */
    public function add(array $data = []) {
        if (!empty($data)) {
            $res = $this->save($data);
            if ($res > 0) {
                return $res;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 修改数据
     * @param $data
     * @return bool|mixed
     */
    public function edit(array $data = []) {
        if (!empty($data)) {
            $res = $this->allowField(true)->save($data,[$this->getPk()=>$data[$this->getPk()]]);
            if ($res) {
                return $data[$this->getPk()];
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 获取无限级数据 2020-07-16
     * @param $where 条件
     * @param string $order 排序
     * @param int $limit_level 查询几级结束
     * @param string $relation_id 关联上下级ID字段名
     * @param string $keyword 返回数组中当期级别的名称
     * @return array
     */
    public function getInfinite($where, $order = '', $limit_level = 0, $relation_id = 'pid', $keyword = 'level') {
        return $this->getInfiniteData($where, $order, $limit_level, $relation_id, $keyword, 0, []);
    }

    /**
     * 无限级数据查询方法 2020-07-16
     * @param $where
     * @param string $order
     * @param int $limit_level
     * @param string $relation_id
     * @param string $keyword
     * @param int $now_level
     * @param array $return_data
     * @return array
     */
    public function getInfiniteData($where, $order = '', $limit_level = 0, $relation_id = 'pid', $keyword = 'level', $now_level = 0, $return_data = []) {
        if (!empty($limit_level)) {
            if ($limit_level <= $now_level) {
                return $return_data;
            }
        }
        if ($now_level == 0) {
            $where[$relation_id] = ['elt', 0];
        }
        if (empty($order)) {
            $order = $this->getPk() . ' desc';
        }
        $array = $this->where($where)->order($order)->select();
        if (empty($array)) {
            return $return_data;
        }

        foreach ($array as $key => $value) {
            $where[$relation_id] = $value[$this->getPk()];
            $value[$keyword] = $now_level;
            $return_data[] = $value;
            $return_data = $this->getInfiniteData($where, $order, $limit_level, $relation_id, $keyword, $now_level + 1, $return_data);
        }
        return $return_data;
    }

    /**
     * 查询符合条件的个数
     * @param $where array 查询条件
     * @return int|string
     */
    public function getCount($where) {
        return $this->where($where)->count($this->getPk());
    }

    /**
     * 生成订单编号 - 不同的表订单编号带不同的大写字母以区分
     * @author changsheng
     * @date 2020-07-16
     * @param string $char 订单编号所带的大写字母
     * @param int $length 订单编号后字符串长度
     * @return int|string
     */
    public function createOrderNumber($char = "", $length = 4) {
        $count = 0;
        do {
            $order_number = $char . date('YmdHis');
            for ($i = 0; $i < $length; $i++) {
                $order_number .= rand(0, 9);
            }
            $count = $this->getCount(['order_number' => $order_number]);   //保证生成的订单编号不会重复
        } while ($count>0);

        return $order_number;
    }

    /**
     * 组合where 条件
     * @param $where_array array 链式二维数组
     */

    public function connect_where($where_array){
        $query = $this;
        if(isset($where_array['hasWhere'])){
            if(!isset($where_array['hasWhere']['name'])||!isset($where_array['hasWhere']['where'])){
                unset($where_array['hasWhere']);
            }
            $query = $query->hasWhere($where_array['hasWhere']['name'],$where_array['hasWhere']['where']);
        }
        if(isset($where_array['with'])){
            $query = $query->with($where_array['with']);
        }
        if(isset($where_array['where'])){
            if(isset($where_array['hasWhere'])){
                //反转数组处理表头
                $where_array['where']=array_flip($where_array['where']);
                foreach ($where_array['where'] as &$value){
                    $value = $this->getModel()->name.".".$value;
                }
                $where_array['where']=array_flip($where_array['where']);
                $query = $query->where($where_array['where']);
            }else{
                $query = $query->where($where_array['where']);
            }
        }
        return $query;
    }

    /**
     * 修改field
     * @param $field
     */
    protected function changeField($field){
        $field = explode(",",$field);
        foreach ($field as &$value){
            $value = $this->getModel()->name.".".$value;
        }
        $field = implode(",",$field);
        return $field;
    }

    /**
     * 修改排序
     * @param string  $order 排序
     */
    protected function changeOrder($order){
        $order = explode(",",$order);
        foreach ($order as &$value){
            $value = $this->getModel()->name.".".$value;
        }
        $order = implode(",",$order);
        return $order;
    }
}
